home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Graphics Plus
/
Graphics Plus.iso
/
msdos
/
utils
/
cad3d2ra.zoo
/
cad3dobj.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-03-14
|
9KB
|
317 lines
/*
* cad3d2obj - the Atari CAD-3D file format
* $Id: cad3dobj.c,v 1.1 1994/03/14 15:22:52 herborth Exp $
*
* Chris Herborth
* March 7/94
*
* These are the functions you need to load a CAD-3D 2.x file and do
* something useful with it. See cad3dobj.h for the structs used
* here.
*
* Compile with -DLITTLE_ENDIAN if you've got a little-endian CPU
* (ex, Intel, Cyrix, AMD).
*
* $Log: cad3dobj.c,v $
* Revision 1.1 1994/03/14 15:22:52 herborth
* Initial revision
*
*/
#include <stdio.h>
#include "cad3dobj.h"
/* Load the header into our CAD3D_HEADER struct */
short get_cad3d_header( FILE *fp, CAD3D_HEADER *head )
{
short retval;
#ifdef LITTLE_ENDIAN
short loop;
#endif
if( fp == NULL || head == NULL )
return -1;
retval = fread( head, sizeof( CAD3D_HEADER ), 1, fp );
if( retval != 1 )
return -1;
/* This is disgusting. I hate Intel. */
#ifdef LITTLE_ENDIAN
head->file_id = swap_short( head->file_id );
head->num_objects = swap_short( head->num_objects );
head->light_a_flag = swap_short( head->light_a_flag );
head->light_b_flag = swap_short( head->light_b_flag );
head->light_c_flag = swap_short( head->light_c_flag );
head->light_a_bright = swap_short( head->light_a_bright );
head->light_b_bright = swap_short( head->light_b_bright );
head->light_c_bright = swap_short( head->light_c_bright );
head->ambient_bright = swap_short( head->ambient_bright );
head->light_a_z = swap_short( head->light_a_z );
head->light_b_z = swap_short( head->light_b_z );
head->light_c_z = swap_short( head->light_c_z );
head->light_a_y = swap_short( head->light_a_y );
head->light_b_y = swap_short( head->light_b_y );
head->light_c_y = swap_short( head->light_c_y );
head->light_a_x = swap_short( head->light_a_x );
head->light_b_x = swap_short( head->light_b_x );
head->light_c_x = swap_short( head->light_c_x );
for( loop = 0; loop < 16; loop++ )
head->obj_palette[loop] = swap_short( head->obj_palette[loop] );
for( loop = 0; loop < 16; loop++ )
head->colour_group[loop] = swap_short( head->colour_group[loop] );
head->palette_type = swap_short( head->palette_type );
head->wireframe_colour = swap_short( head->wireframe_colour );
head->outline_colour = swap_short( head->outline_colour );
#endif
if( head->file_id != CAD3D_MAGIC )
return -2;
return 0;
}
/* Dump a CAD-3D 2.x header in a human-readable format to a stream */
short dump_cad3d_header( FILE *fp, const CAD3D_HEADER *head )
{
short loop;
if( fp == NULL || head == NULL )
return -1;
if( head->file_id == CAD3D_MAGIC )
fprintf( fp, "CAD3D 2.x File\n" );
else
fprintf( fp, "WARNING: Unknown file type %x!\n", head->file_id );
fprintf( fp, "%d objects\n", head->num_objects );
if( head->light_a_flag == 1 )
fprintf( fp, "Light A (%f, %f, %f) is on, brightness = %d.\n",
(float)(head->light_a_x)/100.0,
(float)(head->light_a_y)/100.0,
(float)(head->light_a_z)/100.0, head->light_a_bright );
else
fprintf( fp, "Light A is off.\n" );
if( head->light_b_flag == 1 )
fprintf( fp, "Light B (%f, %f, %f) is on, brightness = %d.\n",
(float)(head->light_b_x)/100.0,
(float)(head->light_b_y)/100.0,
(float)(head->light_b_z)/100.0, head->light_b_bright );
else
fprintf( fp, "Light B is off.\n" );
if( head->light_c_flag == 1 )
fprintf( fp, "Light C (%f, %f, %f) is on, brightness = %d.\n",
(float)(head->light_c_x)/100.0,
(float)(head->light_c_y)/100.0,
(float)(head->light_c_z)/100.0, head->light_c_bright );
else
fprintf( fp, "Light C is off.\n" );
fprintf( fp, "Ambient light brightness = %d.\n", head->ambient_bright );
fprintf( fp, "Colour palette and colour groups:\n" );
for( loop = 0; loop < 16; loop++ )
fprintf( fp, "%2d: 0x%04x [%2d]\n", loop, head->obj_palette[loop],
head->colour_group[loop] );
switch( head->palette_type )
{
case 0:
fprintf( fp, "7-shade palette\n" );
break;
case 1:
fprintf( fp, "14-shade palette\n" );
break;
case 2:
fprintf( fp, "Custom palette\n" );
break;
default:
fprintf( fp, "WARNING: Unknown palette type %d!", head->palette_type );
break;
}
fprintf( fp, "Wireframe colour %d\n", head->wireframe_colour );
fprintf( fp, "Outline colour %d\n", head->outline_colour );
/* char reserved[150]; For future expansion (ha!) */
return 0;
}
/* Completely load a CAD-3D object from a file, including its vertices */
/* and triangles... */
short get_cad3d_object( FILE *fp, CAD3D_OBJECT *obj )
{
short retval;
unsigned short loop;
/* Get the object's name... */
retval = fread( obj->name, sizeof( char ), 9, fp );
if( retval != 9 )
return -1;
/* Get the number of vertices... */
retval = fread( &(obj->num_vertices), sizeof( short ), 1, fp );
if( retval != 1 )
return -1;
#ifdef LITTLE_ENDIAN
obj->num_vertices = swap_short( obj->num_vertices );
#endif
/* Allocate RAM for the vertices and load them... */
obj->vertices = (CAD3D_VERTEX *)malloc( obj->num_vertices
* sizeof( CAD3D_VERTEX ) );
if( obj->vertices == NULL )
return -2;
for( loop = 0; loop < obj->num_vertices; loop++ )
{
retval = get_cad3d_vertex( fp, &(obj->vertices[loop]) );
if( retval != 0 )
return -3;
}
/* Get the number of triangles... */
retval = fread( &(obj->num_triangles), sizeof( short ), 1, fp );
#ifdef LITTLE_ENDIAN
obj->num_triangles = swap_short( obj->num_triangles );
#endif
/* Allocate memory for the triangles and load them... */
obj->triangles = (CAD3D_TRIANGLE *)malloc( obj->num_triangles
* sizeof( CAD3D_TRIANGLE ) );
if( obj->triangles == NULL )
return -4;
for( loop = 0; loop < obj->num_triangles; loop++ )
{
retval = get_cad3d_triangle( fp, &(obj->triangles[loop]) );
if( retval != 0 )
return -5;
}
return 0;
}
/* Dump a CAD-3D 2.x in a human-readable format... */
short dump_cad3d_object( FILE *fp, const CAD3D_OBJECT *obj )
{
fprintf( fp, "Object %s:\n", obj->name );
fprintf( fp, " %d vertices\n", obj->num_vertices );
fprintf( fp, " %d triangles\n", obj->num_triangles );
fprintf( fp, " Vertices and triangles mercifully not dumped.\n" );
return 0;
}
/* Read a vertex from a CAD-3D 2.x object... */
short get_cad3d_vertex( FILE *fp, CAD3D_VERTEX *vert )
{
short retval;
if( fp == NULL || vert == NULL )
return -1;
retval = fread( vert, sizeof( CAD3D_VERTEX ), 1, fp );
if( retval != 1 )
return -2;
#ifdef LITTLE_ENDIAN
vert->x = swap_short( vert->x );
vert->y = swap_short( vert->y );
vert->z = swap_short( vert->z );
#endif
return 0;
}
/* Read a triangle within a CAD-3D 2.x object... */
short get_cad3d_triangle( FILE *fp, CAD3D_TRIANGLE *tri )
{
short retval;
if( fp == NULL || tri == NULL )
return -1;
retval = fread( tri, sizeof( CAD3D_TRIANGLE ), 1, fp );
if( retval != 1 )
return -2;
#ifdef LITTLE_ENDIAN
tri->index_a = swap_short( tri->index_a );
tri->index_b = swap_short( tri->index_b );
tri->index_c = swap_short( tri->index_c );
tri->colour_edge = swap_short( tri->colour_edge );
#endif
return 0;
}
/* Given a CAD-3D 2.x header and a particular triangle in that object, */
/* decide which colour is the "base" colour for that object. CAD-3D */
/* does some shading, which is bogus for rendering; finding the "base" */
/* colour will allow the renderer to do the shading. Note that this */
/* "base" colour isn't the same "base" colour referenced in the CAD-3D */
/* documentation; it's actually the "brightest" of the colours in the */
/* triangle's colour group. Note also that colours are compared very */
/* stupidly; a slightly red colour (0x0100) will be "brighter" than a */
/* very yellow colour (0x0077). If your object has a screwy base */
/* group arry, it will probably come out all red. */
short cad3d_triangle_colour( const CAD3D_HEADER *head,
const CAD3D_TRIANGLE *tri )
{
short tri_colour,
group,
loop,
brightest;
/* the low byte of colour_edge is the colour */
tri_colour = tri->colour_edge & 0x00ff;
group = head->colour_group[tri_colour];
/* Scan the colour palette for the colours in this group. */
brightest = 0x0000;
for( loop = 0; loop < 16; loop++ )
if( head->colour_group[loop] == group
&& head->obj_palette[loop] > brightest )
brightest = head->obj_palette[loop];
/* TODO: replace that > comparison with a real "is colour A brighter */
/* than colour B?" test. */
return brightest;
}
/* Convert a given Atari BIOS colour to a "standard" RGB triad ranging */
/* from 0.0 to 1.0 in each element; note that this assumes the 512- */
/* colour range of the original Atari ST, and will probably produce */
/* a bogus RGB triad for STe/TT/Falcon colour ranges (the STe/TT have */
/* a range of 4096 colours, while the Falcon has 15-bit colour); don't */
/* use it for that. */
short atari2rgb( const short atari, RGB_TRIAD *rgb )
{
rgb->red = (float)( ( atari & 0x0f00 ) >> 8 )/7.0;
rgb->green = (float)( ( atari & 0x00f0 ) >> 4 )/7.0;
rgb->blue = (float)( atari & 0x000f )/7.0;
return 0;
}
#ifdef LITTLE_ENDIAN
short swap_short( const short s )
{
return ( (s & 0x00ff) << 8 ) | ( (s & 0xff00) >> 8 );
}
#endif